<?php
    /**
     * Created by PhpStorm.
     * User: huangzhongwei
     * Date: 2018/10/26
     * Time: 16:39
     */

    namespace app\api\service;

    use app\api\service\Token;
    use app\lib\exception\MissException;
    use app\lib\exception\TokenException;
    use think\Exception;
    use think\facade\Env;
    use think\Loader;
    use app\common\model\Order as OrderModel;
    use think\facade\Log;
    use app\lib\exception\OrderException;

    require_once(Env::get('extend_path') . '/NewWxPay/WxPay.Api.php');
    require_once(Env::get('extend_path') . '/NewWxPay/WxPay.Config.php');

    class Pay
    {
        private $orderNo;
        private $orderID;
        private $config;

        /**
         * 获取orderID;
         *
         * @param $orderID
         *
         * @throws Exception
         */
        function __construct($orderID)
        {
            if (!$orderID) {
                throw new Exception('订单号不允许为NULL');
            }
            $this->orderID = $orderID;
            $this->config  = new \WxPayConfig();
        }

        public function pay()
        {
            $this->checkOrderValid();
            $order = new OrderModel();
            $order = $order->with('order_goods')->get($this->orderID);
//            dd($order);
            (new Order())->checkOrder($order,$this->orderID);
            //            $status = $order->checkOrderStock($this->orderID);
            //            if (!$status['pass'])
            //            {
            //                return $status;
            //            }
            return $this->makeWxPreOrder($order['order_price']);
        }

        // 构建微信支付订单信息
        private function makeWxPreOrder($totalPrice)
        {
            $openid = Token::getCurrentTokenVar('openid');

            if (!$openid) {
                throw new TokenException();
            }
            //       没有命名空间时，记得加反斜杠

            $wxOrderData = new \WxPayUnifiedOrder();
            $wxOrderData->SetOut_trade_no($this->orderNo);
            $wxOrderData->SetTrade_type('JSAPI');
            $wxOrderData->SetTotal_fee($totalPrice * 100);
            $wxOrderData->SetBody('拿一下');
            $wxOrderData->SetOpenid($openid);
            $wxOrderData->SetNotify_url('https://paotui.5188cms.com/api/pay/notify');

            return $this->getPaySignature($wxOrderData);
        }

        /**
         * 向微信请求订单号并生成签名
         *
         * @param $wxOrderData
         *
         * @return array
         * @throws Exception
         * @throws \WxPayException
         */
        private function getPaySignature($wxOrderData)
        {

            $wxOrder = \WxPayApi::unifiedOrder($this->config, $wxOrderData);


            // 失败时不会返回result_code
            if ($wxOrder['return_code'] != 'SUCCESS' || $wxOrder['result_code'] != 'SUCCESS') {
                Log::record($wxOrder, 'error');
                Log::record('获取预支付订单失败', 'error');
                throw new Exception('获取预支付订单失败');
            }
            //        保存到数据库，方便后期向客户端发送模板消息
            $this->recordPreOrder($wxOrder);
            //        生成签名
            $signature = $this->sign($wxOrder);
            return $signature;
        }

        /**
         * 更新数据库中的prepay_id
         *
         * @param $wxOrder
         */
        private function recordPreOrder($wxOrder)
        {
            // 必须是update，每次用户取消支付后再次对同一订单支付，prepay_id是不同的
            OrderModel::where('id', '=', $this->orderID)
                      ->update(['prepay_id' => $wxOrder['prepay_id']]);
        }

        /**
         * 签名
         *
         * @param $wxOrder
         *
         * @return array
         */
        private function sign($wxOrder)
        {
            $jsApiPayData = new \WxPayJsApiPay();
            $jsApiPayData->SetAppid(config('wx.app_id'));
            $jsApiPayData->SetTimeStamp((string)time());
            $rand = md5(time() . mt_rand(0, 1000));
            $jsApiPayData->SetNonceStr($rand);
            $jsApiPayData->SetPackage('prepay_id=' . $wxOrder['prepay_id']);
            $jsApiPayData->SetSignType('md5');
            $sign                 = $jsApiPayData->MakeSign($this->config);
            $rawValues            = $jsApiPayData->GetValues();
            $rawValues['paySign'] = $sign;
            //        appid返回客户端并没有实际作用
            unset($rawValues['appId']);
            return $rawValues;
        }

        private function checkOrderValid()
        {
            $order = OrderModel::where('id', '=', $this->orderID)
                               ->find();
            if (!$order) {
                throw new MissException();
            }
            //        $currentUid = Token::getCurrentUid();
            if (!Token::isValidOperate($order->account_id)) {
                throw new TokenException(
                    [
                        'msg'       => '订单与用户不匹配',
                        'errorCode' => 10003,
                    ]);
            }
            if ($order->state != 1&&$order->state !=6) {
                throw new OrderException([
                                              'msg'       => '订单已支付过啦',
                                              'errorCode' => 80003,
                                              'code'      => 400,
                                          ]);
            }
            $this->orderNo = $order->order_no;
            return true;
        }


    }